[LINUX] Make evtchn device use a dynamic minor number.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 29 Sep 2006 13:20:52 +0000 (14:20 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 29 Sep 2006 13:20:52 +0000 (14:20 +0100)
Also update the code in tools to create the device node if udev fails.
The tools now read the sysfs system to find the minor number needed.

Original patch from  Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
linux-2.6-xen-sparse/include/xen/public/evtchn.h
tools/libxc/xc_linux.c
tools/libxc/xenctrl.h

index 76bfab82e6a0e7c8a206a87e211fe46de09a210a..32f8de5bffb6f55fa086ae7b3fa2ad606c31d32c 100644 (file)
@@ -419,10 +419,9 @@ static struct file_operations evtchn_fops = {
 };
 
 static struct miscdevice evtchn_miscdev = {
-       .minor        = EVTCHN_MINOR,
+       .minor        = MISC_DYNAMIC_MINOR,
        .name         = "evtchn",
        .fops         = &evtchn_fops,
-       .devfs_name   = "misc/evtchn",
 };
 
 static int __init evtchn_init(void)
index 99e294824086d40813090365212726b2f1486383..938d4da2bdde2728a08d85285535be8414eab84a 100644 (file)
@@ -33,9 +33,6 @@
 #ifndef __LINUX_PUBLIC_EVTCHN_H__
 #define __LINUX_PUBLIC_EVTCHN_H__
 
-/* /dev/xen/evtchn resides at device number major=10, minor=201 */
-#define EVTCHN_MINOR 201
-
 /*
  * Bind a fresh port to VIRQ @virq.
  * Return allocated port.
index c803b9a82788ff4ade82676066e28f58df2ddde0..a70307a5425948f1df9891d44e249ef3f1beaedb 100644 (file)
@@ -133,27 +133,95 @@ int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
                       (unsigned long)hypercall);
 }
 
+#define MTAB "/proc/mounts"
+#define MAX_PATH 255
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+static int find_sysfsdir(char *sysfsdir)
+{
+    FILE *fp;
+    char type[MAX_PATH + 1];
+
+    if ( (fp = fopen(MTAB, "r")) == NULL )
+        return -1;
+
+    while ( fscanf(fp, "%*s %"
+                   STR(MAX_PATH)
+                   "s %"
+                   STR(MAX_PATH)
+                   "s %*s %*d %*d\n",
+                   sysfsdir, type) == 2 )
+    {
+        if ( strncmp(type, "sysfs", 5) == 0 )
+            break;
+    }
+
+    fclose(fp);
+
+    return ((strncmp(type, "sysfs", 5) == 0) ? 0 : -1);
+}
+
+int xc_find_device_number(const char *name)
+{
+    FILE *fp;
+    int i, major, minor;
+    char sysfsdir[MAX_PATH + 1];
+    static char *classlist[] = { "xen", "misc" };
+
+    for ( i = 0; i < (sizeof(classlist) / sizeof(classlist[0])); i++ )
+    {
+        if ( find_sysfsdir(sysfsdir) < 0 )
+            goto not_found;
+
+        /* <base>/class/<classname>/<devname>/dev */
+        strncat(sysfsdir, "/class/", MAX_PATH);
+        strncat(sysfsdir, classlist[i], MAX_PATH);
+        strncat(sysfsdir, "/", MAX_PATH);
+        strncat(sysfsdir, name, MAX_PATH);
+        strncat(sysfsdir, "/dev", MAX_PATH);
+
+        if ( (fp = fopen(sysfsdir, "r")) != NULL )
+            goto found;
+    }
+
+ not_found:
+    errno = -ENOENT;
+    return -1;
+
+ found:
+    if ( fscanf(fp, "%d:%d", &major, &minor) != 2 )
+    {
+        fclose(fp);
+        goto not_found;
+    }
+
+    fclose(fp);
+
+    return makedev(major, minor);
+}
+
 #define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
 
 int xc_evtchn_open(void)
 {
     struct stat st;
     int fd;
+    int devnum;
+
+    devnum = xc_find_device_number("evtchn");
 
     /* Make sure any existing device file links to correct device. */
-    if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
-        (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)))
+    if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
+         (st.st_rdev != devnum) )
         (void)unlink(EVTCHN_DEV_NAME);
 
-reopen:
+ reopen:
     if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 )
     {
         if ( (errno == ENOENT) &&
             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
-            (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
-            makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0) )
+             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, devnum) == 0) )
             goto reopen;
 
         PERROR("Could not open event channel interface");
index 0a5cfadd3d1ec48a9448a09e35c488c536e36139..d74c1c8c275f9d45d79a3547bdbab51385ad8d65 100644 (file)
@@ -91,6 +91,16 @@ int xc_interface_open(void);
  */
 int xc_interface_close(int xc_handle);
 
+/*
+ * KERNEL INTERFACES
+ */
+
+/*
+ * Resolve a kernel device name (e.g., "evtchn", "blktap0") into a kernel
+ * device number. Returns -1 on error (and sets errno).
+ */
+int xc_find_device_number(const char *name);
+
 /*
  * DOMAIN DEBUGGING FUNCTIONS
  */